/* include fig01 */
#include	"common.h"

int
main(int argc, char **argv)
{
	int					i, maxi, maxfd, listenfd, connfd, sockfd;
	int					nready, client[1024];
	ssize_t				n;
	fd_set				rset, allset;
	char				buf[MAXLINE];
	socklen_t			clilen;
	struct sockaddr_in	cliaddr, servaddr;
	int ret = 0;
	char 				cliaddr_str[20];

	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		printf("Server socket failed. %d\r\n", listenfd);
		return -1;
	}

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(SERVER_PORT);

	if ((ret = bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0)
	{
		printf("server bind failed. %d \r\n", ret);
		return -1;
	}

	if ((ret = listen(listenfd, 23)) < 0) {
		printf("Server listen failed. %d\r\n", ret);
		return -1;
	}

	maxfd = listenfd;			/* initialize */
	maxi = -1;					/* index into client[] array */
	for (i = 0; i < FD_SETSIZE; i++)
		client[i] = -1;			/* -1 indicates available entry */
	FD_ZERO(&allset);
	FD_SET(listenfd, &allset);
/* end fig01 */

/* include fig02 */
	for ( ; ; ) {
		rset = allset;		/* structure assignment */
		if ((nready = select(maxfd+1, &rset, NULL, NULL, NULL)) < 0) {
			printf("Server select failed %d\r\n", nready);
			return -1;
		}

		if (FD_ISSET(listenfd, &rset)) {	/* new client connection */
			clilen = sizeof(cliaddr);
			if ((connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen)) < 0) {
				printf("Server accept failed. %d\r\n", connfd);
				return -1;
			}
			bzero(cliaddr_str, sizeof(cliaddr_str));
			inet_ntop(AF_INET, &cliaddr.sin_addr, cliaddr_str, sizeof(cliaddr_str));

			printf("new client: %s, port %d\n", cliaddr_str, ntohs(cliaddr.sin_port));

			for (i = 0; i < FD_SETSIZE; i++)
				if (client[i] < 0) {
					client[i] = connfd;	/* save descriptor */
					break;
				}
			if (i == FD_SETSIZE) {
				printf("too many clients");
				return -1;
			}
				

			FD_SET(connfd, &allset);	/* add new descriptor to set */
			if (connfd > maxfd)
				maxfd = connfd;			/* for select */
			if (i > maxi)
				maxi = i;				/* max index in client[] array */

			if (--nready <= 0)
				continue;				/* no more readable descriptors */
		}

		for (i = 0; i <= maxi; i++) {	/* check all clients for data */
			if ( (sockfd = client[i]) < 0)
				continue;
			if (FD_ISSET(sockfd, &rset)) {
				n = recv(sockfd, buf, MAXLINE, 0);
				switch (n) {
					case -1:
						printf("Server read socket %d failed. err_code: %d\r\n", sockfd, (int)n);
						return -1;
					case 0:
						/* connection closed by client */
						if ((ret = close(sockfd)) < 0){
							printf("Server close socket %d failed. err_code: %d\r\n", sockfd, ret);
							return -1;
						}
						printf("Dectect client closed.\r\n");
						FD_CLR(sockfd, &allset);
						client[i] = -1;
						break;
					default:
						printf("receive %d bytes: %d\r\n", (int)n, (int)buf[0]);
						if (send(sockfd, (void *)&buf, n, 0) != n) {
							printf("Server write socket %d failed. \r\n", sockfd);
							return -1;
						}
						break;
				}
				if (--nready <= 0)
					break;				/* no more readable descriptors */
			}
		}
	}
}
/* end fig02 */
